package de.jadehs.cosima.ui.commands;

import java.util.List;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.handlers.HandlerUtil;
import org.eclipse.zest.core.widgets.Graph;
import org.jgrapht.DirectedGraph;

import de.jadehs.cosima.Cosima;
import de.jadehs.cosima.Program;
import de.jadehs.cosima.Regex;
import de.jadehs.cosima.State;
import de.jadehs.cosima.Transition;
import de.jadehs.cosima.TransitionsTable;
import de.jadehs.cosima.converters.DFAToMinimalDFAConverter;
import de.jadehs.cosima.converters.EpsNFAToNFAConverter;
import de.jadehs.cosima.converters.NFAToDFAConverter;
import de.jadehs.cosima.converters.RegexToEpsNFAConverter;
import de.jadehs.cosima.converters.TransitionsTableToDirectedGraphConverter;
import de.jadehs.cosima.ui.CosimaUIUtil;
import de.jadehs.cosima.ui.GraphsView;
import de.jadehs.cosima.ui.converters.DirectedGraphToZestGraphConverter;

public class RenderGraph extends AbstractHandler {
	public Object execute(ExecutionEvent event) throws ExecutionException {
		GraphsView view = (GraphsView) HandlerUtil
				.getActiveWorkbenchWindow(event).getActivePage()
				.findView("de.jadehs.cosima.ui.graphs");

		Composite container = view.getEmptyContainer();
		{
			GridLayout layout = new GridLayout(1, false);
			layout.marginWidth = 2;
			layout.marginHeight = 0;
			container.setLayout(layout);
		}

		Cosima cosima = CosimaUIUtil.getCosimaModel(HandlerUtil
				.getActiveWorkbenchWindow(event).getWorkbench());
		List<Program> progs = cosima.getPrograms();

		for (int i = 0; i < progs.size(); i++) {
			Program p = progs.get(i);

			if (p instanceof Regex) {
				TransitionsTable epsNFA = RegexToEpsNFAConverter.INSTANCE
						.convert((Regex) p);
				render(container, epsNFA, "Regex -> epsilon NFA");

				TransitionsTable nfa = EpsNFAToNFAConverter.INSTANCE
						.convert(epsNFA);
				render(container, nfa, "epsilon NFA -> NFA");

				TransitionsTable dfa = NFAToDFAConverter.INSTANCE.convert(nfa);
				render(container, dfa, "NFA -> DFA");

				TransitionsTable minDFA = DFAToMinimalDFAConverter.INSTANCE
						.convert(dfa);
				render(container, minDFA, "DFA -> minimal DFA");
			} else if (p instanceof TransitionsTable) {
				render(container, (TransitionsTable) p,
						p.getName() == null ? "transitions" : p.getName());
			}
		}

		container.layout();
		return null;
	}

	private void render(Composite parent, TransitionsTable table, String name) {
		if (table == null) {
			return;
		}

		Composite container = new Composite(parent, SWT.None);
		{
			GridLayout layout = new GridLayout(1, false);
			layout.marginWidth = 2;
			layout.marginHeight = 0;
			container.setLayout(layout);
			container.setLayoutData(new GridData(GridData.FILL_BOTH));
		}

		DirectedGraph<State, Transition> dgraph = TransitionsTableToDirectedGraphConverter.INSTANCE
				.convert(table);

		Text l = new Text(container, SWT.READ_ONLY | SWT.NONE);
		{
			l.setText(name);
			l.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		}

		Graph g = new DirectedGraphToZestGraphConverter().convert(dgraph,
				container);
		{
			g.setLayoutData(new GridData(GridData.FILL_BOTH));
		}
	}
}
